﻿/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Net;
using System.IO;
using System.Threading;
using System.Runtime.Serialization.Json;

namespace TranslatorService.Speech
{
    /// <summary>
    /// Contains the access token that you need to use to access the Microsoft Translator API.
    /// </summary> 
    [DataContract]
    public class AdmAccessToken
    {
        /// <summary>
        /// The access token that you can use to authenticate you access to the Microsoft Translator API. 
        /// </summary>
        [DataMember]
        public string access_token { get; set; }
        /// <summary>
        /// The format of the access token. Currently, Azure DataMarket returns http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0, which indicates that a Simple Web Token (SWT) token will be returned.
        /// </summary>
        [DataMember]
        public string token_type { get; set; }
        /// <summary>
        /// The number of seconds for which the access token is valid.
        /// </summary>
        [DataMember]
        public string expires_in { get; set; }
        /// <summary>
        /// The domain for which this token is valid. For the Microsoft Translator API, the domain is http://api.microsofttranslator.com.
        /// </summary>
        [DataMember]
        public string scope { get; set; }
    }

    internal class RequestData
    {
        public WebRequest Request { get; set; }
        public byte[] Data { get; set; }
    }

    internal class AdmAuthentication
    {
        public event EventHandler<GetAccessTokenEventArgs> GetAccessTokenCompleted;

        private const string DATAMARKET_ACCESS_URI = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
        private string clientID;
        private string cientSecret;
        private string request;

        public AdmAuthentication(string clientID, string clientSecret)
        {
            this.clientID = clientID;
            this.cientSecret = clientSecret;

            //If clientid or client secret has special characters, encode before sending request
            this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", Uri.EscapeDataString(clientID), Uri.EscapeDataString(clientSecret));
        }

        public void GetAccessTokenAsync()
        {
            //Prepare OAuth request             
            WebRequest webRequest = WebRequest.Create(DATAMARKET_ACCESS_URI);
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "POST";
            byte[] bytes = Encoding.UTF8.GetBytes(this.request);

            RequestData requestData = new RequestData { Data = bytes, Request = webRequest };
            webRequest.BeginGetRequestStream(requestStreamAsyncResult =>
            {
                var requestStreamData = (RequestData)requestStreamAsyncResult.AsyncState;
                WebRequest sendRequest = requestStreamData.Request;
                byte[] data = requestStreamData.Data;

                // End the operation
                Stream outputStream = sendRequest.EndGetRequestStream(requestStreamAsyncResult);

                // Write to the request stream.
                outputStream.Write(data, 0, data.Length);
                outputStream.Close();

                // Start the asynchronous operation to get the response
                webRequest.BeginGetResponse(getResponseAsyncResult =>
                {
                    WebRequest responseRequest = (WebRequest)getResponseAsyncResult.AsyncState;

                    // End the operation
                    HttpWebResponse webResponse = (HttpWebResponse)responseRequest.EndGetResponse(getResponseAsyncResult);
                    Stream streamResponse = webResponse.GetResponseStream();

                    //Get deserialized object from JSON stream
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                    AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(streamResponse);

                    // Close the stream object
                    streamResponse.Close();

                    // Release the HttpWebResponse
                    webResponse.Close();

                    if (GetAccessTokenCompleted != null)
                        GetAccessTokenCompleted(this, new GetAccessTokenEventArgs(token));
                }
                    , webRequest);

            }, requestData);

        }
    }
}
